#include "PrimitiveSceneInfo.h"
#include "MeshPassProcessor.h"
#include "Runtime/Logic/Component/PrimitiveComponent.h"

namespace Alice
{
    PrimitiveSceneInfo::PrimitiveSceneInfo(PrimitiveComponent* inPrimitiveComponent, Scene* inScene)
        :mPrimitiveComponent(inPrimitiveComponent),mScene(inScene)
    {
        mPrimitiveSceneProxy=inPrimitiveComponent->mPrimitiveSceneProxy;
    }
    void PrimitiveSceneInfo::AddStaticMeshes(CGICommandListBase& RHICmdList, Scene* inScene, std::vector<PrimitiveSceneInfo*> inSceneInfos, bool bCacheMeshDrawCommands)
    {
        for(std::vector<PrimitiveSceneInfo*>::iterator iter=inSceneInfos.begin();iter!=inSceneInfos.end();iter++)
        {
            PrimitiveSceneInfo* SceneInfo = *iter;
            // Cache the primitive's static mesh elements.
            FBatchingSPDI BatchingSPDI(SceneInfo);
            //BatchingSPDI.SetHitProxy(SceneInfo->DefaultDynamicHitProxy);
            SceneInfo->mPrimitiveSceneProxy->DrawStaticElements(&BatchingSPDI);
            //SceneInfo->StaticMeshes.Shrink();
            //SceneInfo->StaticMeshRelevances.Shrink();
            //SceneInfo->bPendingAddStaticMeshes = false;
        }
    }
    void PrimitiveSceneInfo::CacheMeshDrawCommands(Scene* Scene, std::vector<PrimitiveSceneInfo*> SceneInfos)
    {
        const int BATCH_SIZE = 1;//WITH_EDITOR ? 1 : GMeshDrawCommandsBatchSize;
        const int NumBatches = (SceneInfos.size() + BATCH_SIZE - 1) / BATCH_SIZE;
        
        auto DoWorkLambda = [Scene, SceneInfos, BATCH_SIZE](FCachedPassMeshDrawListContext& DrawListContext, int32 Index)
        {
            struct FMeshInfoAndIndex
            {
                int32 InfoIndex;
                int32 MeshIndex;
            };
            int LocalNum = MathUtils::Min((Index * BATCH_SIZE) + BATCH_SIZE, int32(SceneInfos.size()));
            int LocalIndex=Index;
            PrimitiveSceneInfo* sceneInfo = SceneInfos[LocalIndex];
            PrimitiveSceneProxy* sceneProxy = sceneInfo->mPrimitiveSceneProxy;
            sceneInfo->mStaticMeshCommandInfos.resize(1);
            for (int32 PassIndex = 0; PassIndex < EMeshPass::Num; PassIndex++)
            {
			    EMeshPass::Type PassType = (EMeshPass::Type)PassIndex;
                FMeshPassProcessor* PassMeshProcessor = FPassProcessorManager::CreateMeshPassProcessor(EShadingPath::Deferred, PassType, Scene, nullptr, &DrawListContext);
                if (PassMeshProcessor != nullptr)
                {
                    FStaticMeshBatch* meshBatch = sceneInfo->mStaticMeshes[0];
                    FStaticMeshBatchRelevance* meshRelevance = sceneInfo->mStaticMeshRelevances[0];
                    PassMeshProcessor->AddMeshBatch(*meshBatch,0,sceneProxy);
                    FCachedMeshDrawCommandInfo commandInfo=DrawListContext.GetCommandInfoAndReset();
                    if(commandInfo.CommandIndex!=-1||commandInfo.StateBucketId!=-1)
                    {
                        meshRelevance->mCommandInfosMask.Set(PassType);
                        meshRelevance->CommandInfosBase++;
                        int CommandInfoIndex=0*EMeshPass::Num+PassType;
                        FCachedMeshDrawCommandInfo* currentCommandInfo=sceneInfo->mStaticMeshCommandInfos[CommandInfoIndex];
                        *currentCommandInfo=commandInfo;
                    }
                }
            }
            for (int LocalIndex = (Index * BATCH_SIZE); LocalIndex < LocalNum; LocalIndex++)
            {
                
            }
        };
        FCachedPassMeshDrawListContextImmediate DrawListContext(*Scene);
        for (int32 Idx = 0; Idx < NumBatches; Idx++)
        {
            DoWorkLambda(DrawListContext, Idx);
        }
    }
}
